//
// Created by 33145 on 2023/5/28.
//

#include "fdevent.h"
#include "../common/log.h"
#include <string.h>
#include <fcntl.h>

namespace rocket {
  FdEvent::FdEvent(int fd) : _fd(fd) {
    memset(&_listen_events, 0, sizeof(_listen_events));
  }


  FdEvent::FdEvent() {
    memset(&_listen_events, 0, sizeof(_listen_events));
  }

  std::function<void()> FdEvent::handler(TriggerEvent event) {
    if (event == TriggerEvent::IN_EVENT) {
      return _read_callback;
    } else if (event == TriggerEvent::OUT_EVENT) {
      return _write_callback;
    } else if (event == TriggerEvent::ERROR_EVENT) {
      return _error_callback;
    }
    return nullptr;
  }


  void FdEvent::listen(TriggerEvent event_type, std::function<void()> callback, std::function<void()> error_callback /*= nullptr*/) {
    if (event_type == TriggerEvent::IN_EVENT) {
      _listen_events.events |= EPOLLIN;
      _read_callback = callback;
    } else {
      _listen_events.events |= EPOLLOUT;
      _write_callback = callback;
    }

    if (_error_callback == nullptr) {
      _error_callback = error_callback;
    } else {
      _error_callback = nullptr;
    }

    _listen_events.data.ptr = this;
  }


  void FdEvent::cancel(TriggerEvent event_type) {
    if (event_type == TriggerEvent::IN_EVENT) {
      _listen_events.events &= (~EPOLLIN);
    } else {
      _listen_events.events &= (~EPOLLOUT);
    }
  }


  void FdEvent::setNonBlock() {

    int flag = fcntl(_fd, F_GETFL, 0);
    if (flag & O_NONBLOCK) {
      return;
    }

    fcntl(_fd, F_SETFL, flag | O_NONBLOCK);
  }

  int FdEvent::getFd() const {
    return _fd;
  }

  epoll_event FdEvent::getEpollEvent() {
    return _listen_events;
  }
}
